package com.bwie.home.backstage.service.impl;

import com.bwie.home.common.utils.R;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.home.common.utils.PageUtils;
import com.bwie.home.common.utils.Query;
import com.bwie.home.backstage.dao.TeambuyDao;
import com.bwie.home.backstage.entity.TeambuyEntity;
import com.bwie.home.backstage.service.TeambuyService;


@Service("teambuyService")
public class TeambuyServiceImpl extends ServiceImpl<TeambuyDao, TeambuyEntity> implements TeambuyService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private Redisson redisson;
    @Autowired
    private TeambuyDao teambuyDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //（展示已结束的（未逻辑删除状态），按时间倒序排序）
        QueryWrapper<TeambuyEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("buystatus", 0).eq("delstatus", 0).orderByDesc("endtime");
        IPage<TeambuyEntity> page = this.page(
                new Query<TeambuyEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    @Override
    public R updateTeamBuy(int status) {
        String redissonName = "teamBuy_status_type";
        String redisKey = "teamBuy_status";
        return this.updateRedisStatus(redissonName, redisKey, status);
    }

    @Override
    public int getTeamBuy() {
        String s = redisTemplate.opsForValue().get("teamBuy_status");
        if (s == null) {
            return 0;
        } else {
            //open打开
            if ("open".equals(s)) {
                return 1;
            } else
                //close关闭
                if ("close".equals(s)) {
                    return 0;
                }
        }
        return 0;
    }

    @Override
    public R updatePinTeamBuy(int status) {
        String redissonName = "pinTeamBuy_status_type";
        String redisKey = "pinTeamBuy_status";
        return this.updateRedisStatus(redissonName, redisKey, status);
    }

    @Override
    public int getPinTeamBuy() {
        String s = redisTemplate.opsForValue().get("pinTeamBuy_status");
        if (s == null) {
            return 0;
        } else {
            //open打开
            if ("open".equals(s)) {
                return 1;
            } else
                //close关闭
                if ("close".equals(s)) {
                    return 0;
                }
        }
        return 0;
    }

    @Override
    public void dtb(List<Integer> asList) {
        for (Integer i : asList) {
            teambuyDao.dtb(i);
        }
    }

    public R updateRedisStatus(String redissonName, String redisKey, Integer status) {
        String open = "open";
        String close = "close";
        //创建读写锁
        RReadWriteLock lock = redisson.getReadWriteLock(redissonName);
        //创建读锁
        RLock rLock = lock.readLock();
        //加读锁
        rLock.lock(30, TimeUnit.SECONDS);
        //2次校验
        String s = redisTemplate.opsForValue().get(redisKey);
        //释放读锁
        rLock.unlock();
        if (s != null && !"".equals(s)) {
            //如果Redis存在状态
            if (status == 1 && !close.equals(s)) {
                //如果状态和redis不符
                return R.error();
            } else if (status == 0 && !open.equals(s)) {
                //如果状态和redis不符
                return R.error();
            } else {
                //状态相符
                //创建写锁
                RLock writeLock = lock.writeLock();
                //status==1  打开拼团
                if (status == 1) {
                    try {
                        //加写锁
                        writeLock.lock(30, TimeUnit.SECONDS);
                        //覆盖原状态
                        redisTemplate.opsForValue().set(redisKey, open, 24, TimeUnit.HOURS);
                    } finally {
                        //释放写锁
                        writeLock.unlock();
                    }
                    return R.ok().put("status", 1);
                    //status==0  关闭拼团
                } else if (status == 0) {
                    try {
                        //加写锁
                        writeLock.lock(30, TimeUnit.SECONDS);
                        //覆盖原状态
                        redisTemplate.opsForValue().set(redisKey, close, 24, TimeUnit.HOURS);
                    } finally {
                        //释放写锁
                        writeLock.unlock();
                    }
                    return R.ok().put("status", 0);
                } else {
                    //其余状态
                    return R.error();
                }
            }
        } else {
            //不存在，第一次使用
            //创建写锁
            RLock writeLock = lock.writeLock();
            //status==1  打开拼团
            if (status == 1) {
                try {
                    //加写锁
                    writeLock.lock(30, TimeUnit.SECONDS);
                    //覆盖原状态
                    redisTemplate.opsForValue().set(redisKey, open, 24, TimeUnit.HOURS);
                } finally {
                    //释放写锁
                    writeLock.unlock();
                }
                return R.ok().put("status", 1);
                //status==0  关闭拼团
            } else if (status == 0) {
                try {
                    //加写锁
                    writeLock.lock(30, TimeUnit.SECONDS);
                    //覆盖原状态
                    redisTemplate.opsForValue().set(redisKey, close, 24, TimeUnit.HOURS);
                } finally {
                    //释放写锁
                    writeLock.unlock();
                }
                return R.ok().put("status", 0);
            } else {
                //其余状态
                return R.error();
            }
        }
    }
}